/*! \file SharedMemory.h
  \brief Une classe template qui permet de construire des segments de mémoire partagées.
*/

#ifndef SHAREDMEMORY_H
#define	SHAREDMEMORY_H

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string>
#include <cassert>

#include <cstdlib>
#include <sys/msg.h>
#include <stddef.h>

#include "alloc_event_t.h"

/*---------------------------SHARED MEMORY FUNCTIONS-------------------------*/
  
  #define MODE  (int)'R'

/**
 * \class SharedMemory
 * \brief Cette classe permet creer des segment de memoire partagee
 */
template <size_t shmemSize,const enum_keys key_ > 
class SharedMemory{ 
private:
    static key_t key;
    static int shmId;
    static char* data;
    
public:
    /**
     * \brief construit une clef pour partager la memoire
     */
    static  void makeKey();
    /**
     * \brief connect le processus appelant au segment partage
     */
    static  void connectToSegment();
    
    /**
     * \brief renvoie un pointeur vers la zone memoire partagee
     */
    static  char* getPointerToShmem();
    
    /**
     * \brief detache le processus appelant du segment de memoire partagee
     */
    static  void detachSegment();
    
    /**
     * \brief le processus appelant deteruit le segment de memoire partagee
     */
    static void  destroyShmem();
};


template <size_t shmemSize,const enum_keys key_> char* SharedMemory<shmemSize,key_>::data ;
template <size_t shmemSize,const enum_keys key_> key_t SharedMemory<shmemSize,key_>::key;
template <size_t shmemSize,const enum_keys key_> int   SharedMemory<shmemSize,key_>::shmId ;



template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::makeKey(){
        //const char *file =getenv(ipc_keys[key_]);
        fprintf(stderr,"IPC_KEYS: %s\n",ipc_keys[key_]);

        if((key=ftok(ipc_keys[key_],MODE)) == -1){
            perror("ftok");
            exit(1);
        }
}

template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::connectToSegment(){
    
    
        fprintf(stderr,"Construction d'un segment memoire de taille : %lu\n",shmemSize);
        if((shmId= shmget(key,shmemSize,0644 | IPC_CREAT)) == -1){
            //printf("Veuillez fixer correctement la variable d'environnement IPC_KEYS !!\n");
            perror("shmget");
            exit(1);
        }
}

template <size_t shmemSize,const enum_keys key_> char* SharedMemory<shmemSize,key_>::getPointerToShmem(){
    //printf("shmID=%d\n",shmId);
    data=(char*)shmat(shmId,NULL,0);    
    return data;
}


template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::detachSegment(){
if(shmdt(data) == -1){
        perror("shmdt");
        exit(1);
    }
}

template <size_t shmemSize,const enum_keys key_> void SharedMemory<shmemSize,key_>::destroyShmem(){
    if(shmctl(shmId,IPC_RMID,NULL)==-1){
        perror("shmdt");
        exit(1);
    }
}

#endif	/* SHAREDMEMORY_H */

